package com.baosight.risk.common.quartz;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.mail.Address;
import javax.mail.SendFailedException;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailSendException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;

import com.baosight.risk.api.fltd.FltdProcessService;
import com.baosight.risk.api.xtaa.code.IXtaaCodeService;
import com.baosight.risk.common.aspects.factory.AsyncFactory;
import com.baosight.risk.common.email.service.EmailService;
import com.baosight.risk.common.manager.AsyncManager;
import com.baosight.risk.common.utils.DateUtils;
import com.baosight.risk.common.utils.NumberUtil;
import com.baosight.risk.common.utils.StringUtils;
import com.baosight.risk.mapper.system.XsUserMapper;
import com.baosight.risk.mapper.xtaa.code.XtaaCodeMapper;
import com.baosight.risk.mapper.xtzy.XtzyRoleUserMapper;
import com.baosight.risk.mapper.zbva.TZbvaInformationMapper;
import com.baosight.risk.service.system.entity.SysOperLog;
import com.baosight.risk.service.system.entity.XsUser;
import com.baosight.risk.service.xtaa.code.entity.XtaaCode;
import com.baosight.risk.service.zbva.vo.ZbvaInformationEmailVO;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component("zbvaInformationTask")
public class ZbvaInformationTask {
    @Autowired
    private EmailService emailService;
    @Autowired
    private FltdProcessService fltdProcessService;
    @Autowired
    private TZbvaInformationMapper informationMapper;
    @Autowired
    private XtzyRoleUserMapper roleUserMapper;

    @Autowired
    private XtaaCodeMapper xtaaCodeMapper;

    @Autowired
    private JavaMailSender javaMailSender;

    @Value("${mail.fromAddress}")
    private String fromAddress;

    @Autowired
    private XsUserMapper xsUserMapper;
    @Autowired
    private IXtaaCodeService xtaaCodeService;

    public void sendInformation(String params, String jobId) throws Exception {
        List<SysOperLog> logs = new ArrayList<>();
        Exception error = null;
        List<String> emailKey = new ArrayList<String>();
        List<ZbvaInformationEmailVO> voList = parseData(this.dateList());

        if(CollectionUtils.isEmpty(voList)){
        	this.sendToManager();
        	return;
        }
        try {
            log.info("进入定时任务——政策及行业资讯");
            String nowDate = DateUtils.format(new Date(), "yyyy-MM-dd");
            List<Map> list = roleUserMapper.selectSendMailUser();
            for (Map item : list) {
                XsUser userParam = new XsUser();
                userParam.setLoginName(item.get("userCode").toString());
                List<XsUser> emailAddess = xsUserMapper.select(userParam);
                for (int i = 0; i < emailAddess.size(); i++) {
                    if (StringUtils.isNotEmpty(emailAddess.get(i).getEmail()) && this.emailFormat(emailAddess.get(i).getEmail())) {
                        emailKey.add(emailAddess.get(i).getEmail());
                    }
                }
            }
            StringBuffer data = new StringBuffer();
            String[] senderEmailList = emailKey.toArray(new String[emailKey.size()]);
            Map keyEmailMap = this.splitEmali(senderEmailList);
            for (Object keyValue : keyEmailMap.keySet()) {
                if (keyEmailMap.get(keyValue) != null) {
                    String[] bccEmail = keyEmailMap.get(keyValue).toString().split(",");
                    this.sendMessage(bccEmail, createContext(voList), jobId);
                }
            }
            logs.add(fltdProcessService.getLog("发送政策及行业资讯邮件定时任务执行成功", 0, "成功" + senderEmailList.length + "条", jobId));
        } catch (Exception e) {
            logs.add(fltdProcessService.getLog("发送政策及行业资讯邮件定时任务执行失败", 1, e.getMessage(), jobId));
            log.info(e.toString());
        }
        log.info("定时任务——政策及行业资讯完成");
        // 保存日志到数据库
        AsyncManager.me().execute(AsyncFactory.batchRecordOper(logs));
        if (error != null) {
            throw error;
        }

    }


    //发送管理员
    private void sendToManager() {
    	List<XtaaCode> list = xtaaCodeService.selectAllDataByDDTypeCode("MANAGE_MAIL");
    	if(CollectionUtils.isNotEmpty(list)){
            SimpleMailMessage message = new SimpleMailMessage();
            message.setTo("audit@baosteel.com");
            message.setFrom(fromAddress);
            List<String> emails = list.stream().map(XtaaCode::getDdName).collect(Collectors.toList());
            message.setBcc(emails.toArray(new String[]{}));
            message.setSubject("钢铁行业政策及行业资讯没数据");
            message.setText("钢铁行业政策及行业资讯没数据,请检查程序。");
            javaMailSender.send(message);
    	}
    }

    private List<String> dateList(){
        List<String> dateStringList=new ArrayList<String>();
        for (int i = 0; i <7; i++) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Calendar c = Calendar.getInstance();
            c.setTime(new Date());
            c.add(Calendar.DATE, - i);
            Date d = c.getTime();
            dateStringList.add(format.format(d)) ;
        }
       return dateStringList;
    }

    private void sendMessage(String[] bcc, String text, String jobId) {
        List<SysOperLog> logs = new ArrayList<>();
        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setTo("audit@baosteel.com");
            message.setFrom(fromAddress);
            message.setBcc(bcc);
            message.setSubject("钢铁行业政策及行业资讯（" + DateUtils.formatYYYY_MM_DD(new Date()) + "）");
            message.setText(text);
            javaMailSender.send(message);
        } catch (MailSendException e) {
            Set<String> tmpInvalidMails = getInvalidAddress(e);
            // 非无效收件人导致的异常，暂不处理
            if (tmpInvalidMails.isEmpty()) {
                log.info(e.getMessage());
                return;
            }
            if (tmpInvalidMails != null) {
                Object[] array = tmpInvalidMails.toArray();
                String splitSetWithComma = StringUtils.join(array, ",");
                for (String key : tmpInvalidMails) {
                    logs.add(fltdProcessService.getLog("发送政策及行业资讯邮件定时任务无效邮件:", 1, "无效邮件账户：" + key, jobId));
                }

            }
            List<String> stringB = Arrays.asList(bcc);
            List<String> emailNoList = new ArrayList<String>(stringB);
            emailNoList.removeAll(tmpInvalidMails);
            String[] newEmailList = emailNoList.toArray(new String[emailNoList.size()]);
            if (bcc == null) {
                log.info("邮件发送失败，无收件人" + e.getMessage());
                return;
            }
            if (newEmailList != null) {
                SimpleMailMessage message = new SimpleMailMessage();
                message.setTo("audit@baosteel.com");
                message.setFrom(fromAddress);
                message.setBcc(newEmailList);
                message.setSubject("钢铁行业政策及行业资讯（" + DateUtils.formatYYYY_MM_DD(new Date()) + "）");
                message.setText(text);
                javaMailSender.send(message);
            }
        }

    }

    private Map splitEmali(String[] senderEmailList) {
        StringBuffer data = new StringBuffer();
        Map keyEmailMap = new HashMap();
        int count = 1;
        for (int i = 0; i < senderEmailList.length; i++) {
            data.append(senderEmailList[i] + ",");
            count = count + 1;
            if (count == 50) {
                keyEmailMap.put("emailTop" + i, data.toString());
                count = 1;
                data = new StringBuffer();
            }
            if (senderEmailList.length - 1 == i) {
                keyEmailMap.put("emailTop" + i, data.toString());
            }
        }
        return keyEmailMap;
    }

    public static boolean emailFormat(String email) {
        boolean tag = true;
        final String pattern1 = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
        final Pattern pattern = Pattern.compile(pattern1);
        final Matcher mat = pattern.matcher(email);
        if (!mat.find()) {
            tag = false;
        }
        return tag;
    }

    private Set<String> getInvalidAddress(MailSendException e) {
        Set<String> mails = new HashSet<>();
        for (Exception exception : e.getFailedMessages().values()) {
            if (exception instanceof SendFailedException) {
                for (Address address : ((SendFailedException) exception).getInvalidAddresses()) {
                    mails.add(address.toString());
                }
            }
        }
        return mails;
    }

    private List<ZbvaInformationEmailVO> parseData(List<String> dateList) {
        List<ZbvaInformationEmailVO>  returnNames =informationMapper.selectNetNameList();
        for (int i = 0; i <dateList.size() ; i++) {
            List<ZbvaInformationEmailVO> netNames = informationMapper.selectNetName(dateList.get(i));
            List<ZbvaInformationEmailVO> list = informationMapper.selectForEmail(dateList.get(i));
            for (ZbvaInformationEmailVO netNameVO : netNames) {
                for (ZbvaInformationEmailVO vo : list) {
                    if (netNameVO.getNetName().equals(vo.getNetName())) {
                        netNameVO.getVoList().add(vo);
                    }
                }
            }
            for (ZbvaInformationEmailVO netNameList : netNames) {
                netNameList.setVoList(netNameList.getVoList().subList(0,1));
            }

            for (ZbvaInformationEmailVO itemString: returnNames) {
                for (ZbvaInformationEmailVO netNameListVO : netNames) {
                    if (netNameListVO.getNetName().equals(itemString.getNetName())) {
                        //itemString.setVoList(netNameListVO.getVoList());
                        itemString.getVoList().add(netNameListVO.getVoList().get(0));

                    }
                }
            }

        }

        return returnNames;
    }

    private String createContext(List<ZbvaInformationEmailVO> voList) {
        StringBuffer context = new StringBuffer();
        context.append("宝钢股份全面风险管理系统为您汇总一周钢铁行业相关资讯如下，以下资讯皆来源于互联网，版权归原作者所有，请点击链接查看原文！\n");
        for (int i = 0; i < voList.size(); i++) {
            ZbvaInformationEmailVO information = voList.get(i);
            context.append("  " + NumberUtil.int2chineseNum(i + 1) + "、" + information.getNetName());
            context.append("\n");
            List<ZbvaInformationEmailVO> vos = information.getVoList();
            for (int j = 0; j < vos.size(); j++) {
                ZbvaInformationEmailVO vo = vos.get(j);
                context.append("    " + (j + 1) + "、" + vo.getTitle() + "（" + DateUtils.formatYYYY_MM_DD(vo.getPostDate()) + "）");
                context.append("\n");
                context.append("      " + vo.getPostUrl());
                context.append("\n");
            }
        }
        context.append("\n");
        context.append("\n");
        context.append("最新宏观经济指标变化，请使用公司内网通过电脑端登入http://risk.baogang.info/#/home，登录账号、密码同协同办公平台；\n或通过公司协同办公系统登入，路径：智慧工作平台——应用——业务系统——股份全面风险管理系统（暂不支持手机、平板等移动端登入）。");
        return context.toString();
    }


}
